/****************************************************************************
 * 
 * FILENAME
 *     Audio_Demo.c
 *
 * VERSION
 *     1.0 
 *
 * DESCRIPTION
 *
 *
 *
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *
 *
 *     
 * HISTORY
 *     2004.08.04		Created by Yung-Chang Huang
 *
 *
 * REMARK
 *     None
 *
 **************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"


#include "NUC900_reg.h"
#include "NUC900_Audio.h"



//#define TEST_AC97
#define TEST_I2S

//#define PLAY_DMA_LEN		4096
UINT32 PCM_QUEUE_LEN		=	(512*1024);



#undef getchar
#define getchar		sysGetChar
#define printf		sysprintf


#define get_timer_ticks()	sysGetTicks(TIMER0)

//static UINT8  *_pucPcmQueuePTR = (UINT8 *)(0x180000 | 0x10000000);
static UINT8  _Queue [] = {
	//#include "44.1k.dat"
	#include "Inc/8k.dat"
	//#include "32k.dat"
	//#include "48k.dat"
	
	
};
static UINT8 *_pucPcmQueuePTR;
//static PUINT8 _PLAY_DMA_PTR;

//static UINT8 g_PLAY_DMA_PTR[PLAY_DMA_LEN];

volatile UINT32 _uPcmQHead, _uPcmQTail;

/*UINT8 _sine_wave[192] = 
{
    0x00, 0x00, 0x00, 0x00, 0xb5, 0x10, 0xb5, 0x10, 0x21, 0x21, 0x21, 0x21, 0xfc, 0x30, 0xfc, 0x30, 
    0x00, 0x40, 0x00, 0x40, 0xec, 0x4d, 0xec, 0x4d, 0x82, 0x5a, 0x82, 0x5a, 0x8d, 0x65, 0x8d, 0x65, 
    0xda, 0x6e, 0xda, 0x6e, 0x42, 0x76, 0x42, 0x76, 0xa3, 0x7b, 0xa3, 0x7b, 0xe8, 0x7e, 0xe8, 0x7e, 
    0xff, 0x7f, 0xff, 0x7f, 0xe8, 0x7e, 0xe8, 0x7e, 0xa3, 0x7b, 0xa3, 0x7b, 0x42, 0x76, 0x42, 0x76, 
    0xda, 0x6e, 0xda, 0x6e, 0x8d, 0x65, 0x8d, 0x65, 0x82, 0x5a, 0x82, 0x5a, 0xec, 0x4d, 0xec, 0x4d, 
    0x00, 0x40, 0x00, 0x40, 0xfc, 0x30, 0xfc, 0x30, 0x21, 0x21, 0x21, 0x21, 0xb5, 0x10, 0xb5, 0x10, 
    0x00, 0x00, 0x00, 0x00, 0x4b, 0xef, 0x4b, 0xef, 0xdf, 0xde, 0xdf, 0xde, 0x04, 0xcf, 0x04, 0xcf, 
    0x00, 0xc0, 0x00, 0xc0, 0x14, 0xb2, 0x14, 0xb2, 0x7e, 0xa5, 0x7e, 0xa5, 0x73, 0x9a, 0x73, 0x9a, 
    0x26, 0x91, 0x26, 0x91, 0xbe, 0x89, 0xbe, 0x89, 0x5d, 0x84, 0x5d, 0x84, 0x18, 0x81, 0x18, 0x81, 
    0x01, 0x80, 0x01, 0x80, 0x18, 0x81, 0x18, 0x81, 0x5d, 0x84, 0x5d, 0x84, 0xbe, 0x89, 0xbe, 0x89, 
    0x26, 0x91, 0x26, 0x91, 0x73, 0x9a, 0x73, 0x9a, 0x7e, 0xa5, 0x7e, 0xa5, 0x14, 0xb2, 0x14, 0xb2, 
    0x00, 0xc0, 0x00, 0xc0, 0x04, 0xcf, 0x04, 0xcf, 0xdf, 0xde, 0xdf, 0xde, 0x4b, 0xef, 0x4b, 0xef
};	*/


INT  play_callback(UINT8 *pucBuff, UINT32 uDataLen)
{
	INT		nLen;
	

	nLen = PCM_QUEUE_LEN - _uPcmQHead;

	if (nLen >= uDataLen)
	{
		memcpy(pucBuff, &_pucPcmQueuePTR[_uPcmQHead], uDataLen);
		_uPcmQHead = (_uPcmQHead + uDataLen) % PCM_QUEUE_LEN;
	}
	else
	{
		memcpy(pucBuff, &_pucPcmQueuePTR[_uPcmQHead], nLen);
		memcpy(&pucBuff[nLen], _pucPcmQueuePTR, uDataLen - nLen);
		_uPcmQHead = uDataLen - nLen;

	}

	
	return 0;
}


INT  record_callback(UINT8 *pucBuff, UINT32 uDataLen)
{
	INT		nLen;

	nLen = PCM_QUEUE_LEN - _uPcmQTail;
	if (nLen >= uDataLen)
	{
		memcpy(&_pucPcmQueuePTR[_uPcmQTail], pucBuff, uDataLen);
		_uPcmQTail = (_uPcmQTail + uDataLen) % PCM_QUEUE_LEN;
	}
	else
	{
		memcpy(&_pucPcmQueuePTR[_uPcmQTail], pucBuff, nLen);
		memcpy(_pucPcmQueuePTR, &pucBuff[nLen], uDataLen - nLen);
		_uPcmQTail = uDataLen - nLen;
	}
	return 0;
}


void audio_demo(int choose, int channels)
{
	INT		nTime0,nTime1,temphead;
	WAVEFORMATEX formatTex;
	AU_DEV_E eDev;
	UINT32   nvolume;

	temphead = _uPcmQHead = _uPcmQTail = 0;

	printf("************ User's Guide for Audio Demo ************\n");
	printf("Describtion:This demo program work with AC'97 codec\n");
	printf("            on the W90P910 EV board.\n");
	printf("            There will be about 5 sec music playback then stop.\n");
	printf("    Setting:1. SW1 AC97 1~5 must be \"ON\"\n");
	printf("            2. Output device(head phone or speaker) is required\n");
	printf("     Result:It can play  the song 5 sec normally then exit\n");
	printf("************                             ************\n");
	sysprintf("\n\nPress any key to start...\n");
	sysGetChar();
	printf("starting audio demo...\n");
	
    formatTex.sChannels = (UINT16)channels;
	formatTex.nSamplesPerSec = (UINT32)choose;
	formatTex.fnWAVCallBack = play_callback;

#ifdef TEST_I2S
	{
		//outpw(REG_CLKEN,inpw(REG_CLKEN)&~(2));//ACLK off
		if (choose%AU_SAMPLE_RATE_8000==0)
		{
			outpw(REG_PLLCON1, 0x92E7);//PLL1=122.88MHz
			outpw(REG_CLKDIV,inpw(REG_CLKDIV) & ~(0xF<<8) | (9<<8));
			outpw(REG_CLKSEL,inpw(REG_CLKSEL)&~(3<<4) | (1<<4));//ACLK from PLL1
		}
		else
		{
			//outpw(REG_PLLCON1,0x0380);////PLL1=67.5Mhz
			outpw(REG_PLLCON1, 0x4E25);////PLL1=169.34MHz
			outpw(REG_CLKDIV,inpw(REG_CLKDIV) & ~(0xF<<8) | (9<<8));
			outpw(REG_CLKSEL,inpw(REG_CLKSEL)&~(3<<4) | (1<<4));//ACLK from PLL1
		}
		//outpw(REG_CLKEN,inpw(REG_CLKEN)| 2);//ACLK on
		//while(i--);
	}
#endif

	
#ifdef TEST_AC97
    eDev = 	AU_DEV_AC97;
#else
    eDev =  AU_DEV_I2S;    
#endif
    WAV_Open(WAPI_OUT,&formatTex,eDev);

#ifdef TEST_I2S
	nvolume = 0xa000a;
    WAV_IOControl(WAPI_OUT,WPDM_SETPLAYVOLUME,(UINT32)&nvolume,NULL,eDev);
#endif

	WAV_IOControl(WAPI_OUT,WPDM_START,(UINT32)&formatTex,NULL,eDev);

	
	//while(i--);	
	nTime1 = nTime0 = get_timer_ticks();
	
	while (1)
	{
		if ((get_timer_ticks() - nTime0) >= 100)
		{
			if (temphead == _uPcmQHead)
			{
				//printf("playback hang\n");
				//while(1);
			}
			else
				temphead = _uPcmQHead;
			nTime0 = get_timer_ticks();
			printf("H=%d, T=%d\n", _uPcmQHead/1024, _uPcmQTail/1024);
		}
		//if (get_timer_ticks() > (nTime1 + 500))
		//if ((_uPcmQHead/1024)>=596)
		//{
		//	printf("\n");
		//}
		/*if (_uPcmQHead>=(PCM_QUEUE_LEN-4096))
		{
			//outpw(0xe8000000,0x12345678);
		}*/
		if (get_timer_ticks()> (nTime1+500))
		    break;
		
			//
	}
	WAV_Close(WAPI_OUT,eDev);

}


INT diag_audio(VOID)
{
	PCM_QUEUE_LEN = sizeof (_Queue);
	_pucPcmQueuePTR = (UINT8 *)((int)&_Queue);
    
	/* 
	 * CLK select: SYSTEM_S from UPLL, AUDIO_S from APLL 
	 * SENSOR_S and VIDEO_S from crystal in 
	 */
    audio_demo(AU_SAMPLE_RATE_8000,2);//ok
    
    return 0;

}


